package com.lfy.fyadmin.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.lfy.fyadmin.common.BusinessException;
import com.lfy.fyadmin.common.ErrorCode;
import com.lfy.fyadmin.dto.CaptchaResponse;
import com.lfy.fyadmin.dto.LoginRequest;
import com.lfy.fyadmin.dto.LoginResponse;
import com.lfy.fyadmin.entity.User;
import com.lfy.fyadmin.service.AuthService;
import com.lfy.fyadmin.service.UserService;
import com.lfy.fyadmin.util.CaptchaUtil;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 认证服务实现类
 */
@Service
public class AuthServiceImpl implements AuthService {
    
    private final StringRedisTemplate redisTemplate;
    private final UserService userService;
    
    private static final String CAPTCHA_PREFIX = "captcha:";
    private static final int CAPTCHA_EXPIRE_MINUTES = 5;
    
    public AuthServiceImpl(StringRedisTemplate redisTemplate, UserService userService) {
        this.redisTemplate = redisTemplate;
        this.userService = userService;
    }
    
    @Override
    public CaptchaResponse generateCaptcha() {
        // 生成验证码
        String code = CaptchaUtil.generateCode();
        String captchaKey = UUID.randomUUID().toString();
        
        // 存储到Redis，设置过期时间
        redisTemplate.opsForValue().set(
            CAPTCHA_PREFIX + captchaKey, 
            code, 
            CAPTCHA_EXPIRE_MINUTES, 
            TimeUnit.MINUTES
        );
        
        // 生成图片
        String captchaImage = CaptchaUtil.generateImage(code);
        
        CaptchaResponse response = new CaptchaResponse();
        response.setCaptchaKey(captchaKey);
        response.setCaptchaImage(captchaImage);
        
        return response;
    }
    
    @Override
    public LoginResponse login(LoginRequest loginRequest) {
        // 验证验证码
        validateCaptcha(loginRequest.getCaptchaKey(), loginRequest.getCaptcha());
        
        // 查询用户
        User user = getUserByUsername(loginRequest.getUsername());
        
        // 验证密码
        validatePassword(user, loginRequest.getPassword());
        
        // 检查用户状态
        validateUserStatus(user);
        
        // 生成token
        StpUtil.login(user.getId());
        String token = StpUtil.getTokenValue();
        
        // 构建响应
        LoginResponse response = new LoginResponse();
        response.setToken(token);
        response.setUserId(user.getId());
        response.setUsername(user.getUsername());
        response.setRealName(user.getRealName());
        response.setAvatar(user.getAvatar());
        
        // 删除验证码
        redisTemplate.delete(CAPTCHA_PREFIX + loginRequest.getCaptchaKey());
        
        return response;
    }
    
    @Override
    public void logout() {
        StpUtil.logout();
    }
    
    /**
     * 验证验证码
     */
    private void validateCaptcha(String captchaKey, String captcha) {
        if (!StringUtils.hasText(captchaKey) || !StringUtils.hasText(captcha)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "验证码不能为空");
        }
        
        String storedCaptcha = redisTemplate.opsForValue().get(CAPTCHA_PREFIX + captchaKey);
        if (!StringUtils.hasText(storedCaptcha)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "验证码已过期");
        }
        
        if (!captcha.equalsIgnoreCase(storedCaptcha)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "验证码错误");
        }
    }
    
    /**
     * 根据用户名查询用户
     */
    private User getUserByUsername(String username) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username)
                   .eq(User::getDeleted, 0);
        
        User user = userService.getOne(queryWrapper);
        if (user == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "用户名或密码错误");
        }
        
        return user;
    }
    
    /**
     * 验证密码
     */
    private void validatePassword(User user, String password) {
        String encryptedPassword = encryptPassword(password, user.getSalt());
        if (!encryptedPassword.equals(user.getPassword())) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "用户名或密码错误");
        }
    }
    
    /**
     * 检查用户状态
     */
    private void validateUserStatus(User user) {
        if (user.getStatus() == null || user.getStatus() != 1) {
            throw new BusinessException(ErrorCode.FORBIDDEN, "用户已被禁用");
        }
    }
    
    /**
     * 密码加密
     */
    public String encryptPassword(String password, String salt) {
        return DigestUtils.md5DigestAsHex((password + salt).getBytes());
    }
}